package com.uw.uwrpc.core.util;

import com.alibaba.fastjson.JSON;
import com.uw.uwrpc.core.exception.RpcException;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Array;
import java.util.HashMap;
import java.util.List;

public class TypeUtil {
    private TypeUtil() {
    }


    public static Object cast(Object origin, Class<?> type) {
        Class<?> aClass = origin.getClass();
        if (ObjectUtils.isEmpty(origin) || type.isAssignableFrom(aClass)) {
            return origin;
        }

        if (origin instanceof HashMap<?, ?>) {
            return JSON.parseObject(JSON.toJSONString(origin), type);
        }

        if (type.equals(String.class)) {
            return origin.toString();
        }

        if (type.isArray()) {
            if (origin instanceof List<?> list) {
                origin = list.toArray();
            }

            Class<?> componentType = type.getComponentType();
            int length = Array.getLength(origin);

            Object resultArray = Array.newInstance(componentType, length);
            for (int i = 0; i < length; i++) {
                Array.set(resultArray, i, cast(Array.get(origin, i), componentType));
            }
            return resultArray;
        }

        if (type.equals(Integer.class) || type.equals(Integer.TYPE)) {
            return Integer.valueOf(origin.toString());
        } else if (type.equals(Long.class) || type.equals(Long.TYPE)) {
            return Long.valueOf(origin.toString());
        } else if (type.equals(Short.class) || type.equals(Short.TYPE)) {
            return Short.valueOf(origin.toString());
        } else if (type.equals(Double.class) || type.equals(Double.TYPE)) {
            return Double.valueOf(origin.toString());
        } else if (type.equals(Float.class) || type.equals(Float.TYPE)) {
            return Float.valueOf(origin.toString());
        } else if (type.equals(Byte.class) || type.equals(Byte.TYPE)) {
            return Byte.valueOf(origin.toString());
        } else if (type.equals(Character.class) || type.equals(Character.TYPE)) {
            char[] charArray = origin.toString().toCharArray();
            return charArray[0];
        } else if (type.equals(Boolean.class) || type.equals(Boolean.TYPE)) {
            return Boolean.valueOf(origin.toString());
        }

        throw new RpcException("cast " + type + " error with " + origin);
    }

    public static Object[] cast(Object[] originList, List<Class<?>> typeList) {
        if (ObjectUtils.isEmpty(originList)) {
            return originList;
        }

        int length = originList.length;
        if (length != typeList.size()) {
            throw new RpcException("originList length != typeList size");
        }

        Object[] result = new Object[length];

        for (int i = 0; i < length; i++) {
            result[i] = cast(originList[i], typeList.get(i));
        }

        return result;
    }

}
